<?php
//第一版简单的射手，激光兵，军队！
/*abstract class Unit{
    abstract function bombardStrength();
}

//射手
class Archer extends Unit{
    public function bombardStrength()
    {
        return 4;
    }
}

//激光兵
class LaserCannonUnit extends Unit{
    public function bombardStrength()
    {
        return 44;
    }
}*/

//军队类（由多个兵种组成）
/*class Army{
    private $unit = array();

    public function addUnit(Unit $unit){
        array_push($this->unit,$unit);
    }

    public function bombardStrength(){
        $ret = 0;
        foreach($this->unit as $unit){
            $ret += $unit->bombardStrength();
        }
        return $ret;
    }
}*/


//第二版
//需求变更 ，增加，军对也能与军队组合，而且能分离出来(如果军队还有防御，移动速度等)

/*class Army{
    private $unit = array();
    private $army = array();

    public function addUnit(Unit $unit){
        array_push($this->unit,$unit);
    }

    public function addArmy(Army $army){
        array_push($this->army,$army);
    }

    public function bombardStrength(){
        $ret = 0;
        foreach($this->unit as $unit){
            $ret += $unit->bombardStrength();
        }

        foreach($this->army as $army){
            $ret += $army->bombardStrength();
        }
        return $ret;
    }
}*/

//第三版 增加了运兵船 问题：这样射手和激光兵就需要实现自己不需要的方法 addUnit和removeUnit! 可以用在父类（Unit）中实现方法抛出异常，这样不用在每个子类里面去写了！让军队类去覆盖addUnit和removeUnit
/*abstract class Unit{
    abstract function addUnit(Unit $unit);
    abstract function removeUnit(Unit $unit);
    abstract function bombardStrength();
}

//射手
class Archer extends Unit{

    public function addUnit(Unit $unit){
        throw new Exception('不能用啊');
    }

    public function removeUnit(Unit $unit){
        throw new Exception('不能用啊');
    }

    public function bombardStrength()
    {
        return 4;
    }
}

//激光兵
class LaserCannonUnit extends Unit{

    public function addUnit(Unit $unit){
        throw new Exception('不能用啊');
    }

    public function removeUnit(Unit $unit){
        throw new Exception('不能用啊');
    }
    public function bombardStrength()
    {
        return 44;
    }
}

class Army{
    private $units = array();

    public function addUnit(Unit $unit){
        array_push($this->units,$unit);
    }

    public function removeUnit(Unit $unit){
        $this->units = array_udiff($this->units,array($unit),function($a,$b){
            return ($a === $b)?0:1;
        });
    }
    public function bombardStrength(){
        $ret = 0;
        foreach($this->unit as $unit){
            $ret += $unit->bombardStrength();
        }

        foreach($this->army as $army){
            $ret += $army->bombardStrength();
        }
        return $ret;
    }
}*/

//版本四，为了去掉子类中的addUnit和removeUnit!所以多加了一个类，客户端使用的时候需要自己去判断！
abstract class Unit{
    function getComposite(){
        return null;
    }
    abstract function bombardStrength();
}

abstract class CompositeUnit extends Unit{
    private $units = array();
    function getComposite(){
        return $this;
    }
    protected function getUnits(){
        return $this->units;
    }
    public function addUnit(Unit $unit){
        array_push($this->units,$unit);
    }

    public function removeUnit(Unit $unit){
        $this->units = array_udiff($this->units,array($unit),function($a,$b){
            return ($a === $b)?0:1;
        });
    }

}
